package cn.signalpha.modules.shop.service;

import cn.hutool.core.util.NumberUtil;
import cn.signalpha.core.log.exception.ServiceException;
import cn.signalpha.core.tool.utils.DateUtil;
import cn.signalpha.core.tool.utils.ObjectUtil;
import cn.signalpha.core.tool.utils.StringUtil;
import cn.signalpha.modules.shop.entity.*;
import cn.signalpha.modules.shop.entity.enums.TransportChargeTypeEnum;
import cn.signalpha.modules.shop.mapper.TransportMapper;
import cn.signalpha.modules.shop.vo.OrderConfirmVO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;


/**
 * 运费模版 服务类
 *
 * @author suguangjun
 */
@Service
@AllArgsConstructor
public class TransportService extends ServiceImpl<TransportMapper, Transport> {

	private final GoodsService goodsService;
	private final GoodsSkuService goodsSkuService;
    private final TransportFeeService transportFeeService;
    private final TransportFeeFreeService transportFeeFreeService;

	/**
	 * 计算运费
	 */
	public double calculateTransportFee(OrderConfirmVO.SellerCartItemVO goodsItem, UserAddress userAddr) {
		Goods goods = goodsService.getById(goodsItem.getGoodsId());
		// 用户所在城市id
		String city = userAddr.getCity();

		//找出该产品的运费项
		Transport transport = this.getTransport(goods.getTransportId());
		//商家把运费模板删除
		if (ObjectUtil.isEmpty(transport)) {
			return 0.0;
		}

		//不存在直接不支持配送
		TransportFee transportFeeTemp = null;
		for (TransportFee dbTransportFee : transport.getTransportFeeList()) {
			if(dbTransportFee.getCityArr().contains(city)){
				transportFeeTemp = dbTransportFee;
				break;
			}
		}
		if(transportFeeTemp == null){
			throw new ServiceException("该地区暂不支持配送");
		}

		if (transport.getIsFree() == 1) {
			return 0.0;
		}

		// 用于计算运费的件数
		Double piece = 0.0;
		GoodsSku goodsSku = goodsSkuService.getById(goodsItem.getGoodsSkuId());
		if (Objects.equals(TransportChargeTypeEnum.COUNT.value(), transport.getChargeType())) {
			// 按件数计算运费
			piece = Double.valueOf(goodsItem.getGoodsNum());
		} else if (Objects.equals(TransportChargeTypeEnum.WEIGHT.value(), transport.getChargeType())) {
			// 按重量计算运费
			Double weight = goodsSku.getWeight() == null ? 0 : goodsSku.getWeight();
			piece = NumberUtil.mul(weight, goodsItem.getGoodsNum()).doubleValue();
		} else if (Objects.equals(TransportChargeTypeEnum.VOLUME.value(), transport.getChargeType())) {
			// 按体积计算运费
			Double volume = goodsSku.getVolume() == null ? 0 : goodsSku.getVolume();
			piece = NumberUtil.mul(volume, goodsItem.getGoodsNum()).doubleValue();
		}

		//如果有包邮的条件
		if (transport.getIsFreeCondition() == 1) {
			// 获取所有的包邮条件
			List<TransportFeeFree> transportFeeFrees = transport.getTransportFeeFreeList();
			for (TransportFeeFree transportFeeFree : transportFeeFrees) {
				if(StringUtil.isBlank(transportFeeFree.getFreeCityArr()) || transportFeeFree.getFreeCityArr().contains(city)){
					//包邮方式 （0 满x件/重量/体积包邮 1满金额包邮 2满x件/重量/体积且满金额包邮）
					if ((transportFeeFree.getFreeType() == 0 && piece >= transportFeeFree.getAmount()) ||
						(transportFeeFree.getFreeType() == 1 && goodsItem.getGoodsTotalPrice() >= transportFeeFree.getPiece()) ||
						(transportFeeFree.getFreeType() == 2 && piece >= transportFeeFree.getAmount() && goodsItem.getGoodsTotalPrice() >= transportFeeFree.getPiece())) {
						return 0.0;
					}
				}
			}
		}

		//订单的运费项
		TransportFee transportFee = null;
		List<TransportFee> transportFeeList = transport.getTransportFeeList();
		for (TransportFee dbTransportFee : transportFeeList) {
			// 将该商品的运费设置为默认运费
			if (ObjectUtil.isEmpty(transportFee) && StringUtil.isBlank(dbTransportFee.getCityArr())) {
				transportFee = dbTransportFee;
				continue;
			}
			// 如果在运费模板中的城市找到该商品的运费，则将该商品由默认运费设置为该城市的运费
			if(dbTransportFee.getCityArr().contains(city)){
				transportFee = dbTransportFee;
				break;
			}
		}

		// 如果无法获取到任何运费相关信息，则返回0运费
		if (ObjectUtil.isEmpty(transportFee)) {
			return 0.0;
		}

		// 产品的运费
		double fee = transportFee.getFirstFee();
		// 如果件数大于首件数量，则开始计算超出的运费
		if (piece > transportFee.getFirstPiece()) {
			// 续件数量
			Double prodContinuousPiece = NumberUtil.sub(piece, transportFee.getFirstPiece());
			// 续件数量的倍数，向上取整
			Integer mulNumber = (int) Math.ceil(NumberUtil.div(prodContinuousPiece, transportFee.getContinuousPiece()));
			// 续件数量运费
			double continuousFee = NumberUtil.mul(mulNumber, transportFee.getContinuousFee()).doubleValue();
			fee = NumberUtil.add(fee, continuousFee);
		}
		return fee;
	}

    /**
     * 获取运费模板以及所有子项
     */
    public Transport getTransport(Long id) {
		Transport transport = baseMapper.selectById(id);
		if(transport != null){
			transport.setTransportFeeList(transportFeeService.listByTransportId(id));
			transport.setTransportFeeFreeList(transportFeeFreeService.listByTransportId(id));
		}
        return transport;
    }


	/**
	 * 提交运费模板
	 */
	@Transactional(rollbackFor = Exception.class)
	public boolean submit(Transport transport) {
		if(ObjectUtil.isNotEmpty(transport.getId())){
			// 删除所有的运费项和指定包邮条件项
			transportFeeService.removeByTransportId(transport.getId());
			transportFeeFreeService.removeByTransportId(transport.getId());
		}else{
			transport.setCreateTime(DateUtil.now());
		}
		saveOrUpdate(transport);

		transport.getTransportFeeList().forEach(transportFee -> {
			if(transportFee.getFirstPiece() <= 0){
				throw new ServiceException("首件数必须大于0");
			}
			if(transportFee.getContinuousPiece() <= 0){
				throw new ServiceException("续费数必须大于0");
			}
			transportFee.setTransportId(transport.getId());
		});
		transportFeeService.saveBatch(transport.getTransportFeeList());

		if (transport.getIsFreeCondition() == 1) {
			transport.getTransportFeeFreeList().forEach(item -> item.setTransportId(transport.getId()));
			transportFeeFreeService.saveBatch(transport.getTransportFeeFreeList());
		}
		return true;
	}

    /**
     * 删除运费模板
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean removeTransport(List<Long> transportIds) {
		transportFeeService.removeByTransportIds(transportIds);
		transportFeeFreeService.removeByTransportIds(transportIds);
        return this.removeByIds(transportIds);
    }

}
